package com.bb.flow.util;

import com.bb.flow.config.enumtype.DataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author bigbeard
 * 工具类
 */
public class Tools {

    public static final String NULL_FLOW_TEXT_INFO = "NULL";
    private final static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private final static Logger logger = LoggerFactory.getLogger(Tools.class);
    private static final String SETTER_START = "set";

    /**
     * 判断字符串是否为空,空字符串和null
     *
     * @param value 字符串信息
     * @return true:空或者null,否则不为空
     */
    public static boolean isEmptyOrNull(String value) {
        return "".equals(value) || null == value;
    }

    /**
     * 数据类型转换
     *
     * @param type             原数据数据类型
     * @param value            数据的字符串表示
     * @param flowTemplateName 当前流程模版名称
     * @param nodeKey          当前流程中的节点名称
     * @return 转换到JAVA中的类型后的值
     */
    public static Object parseValue(DataType type, String value, String flowTemplateName, String nodeKey) {

        if ("".equals(value) || null == value) {
            return null;
        }
        if (type == DataType.STRING) {
            return value;
        } else if (type == DataType.DATETIME) {
            SimpleDateFormat sDateFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
            try {
                return sDateFormat.parse(value);
            } catch (ParseException e) {
                logger.error("流程模版[{}]中的节点[{}]中的数据值的日期格式配置出错,目前仅仅支持[" + DATE_TIME_FORMAT + "],配置值为(错误的)[{}]", flowTemplateName, nodeKey, value);
                return null;
            }
        } else if (type == DataType.DECIMAL) {
            return Double.parseDouble(value);
        } else if (type == DataType.BOOLEAN) {
            return Boolean.parseBoolean(value);
        } else if (type == DataType.INT) {
            return Integer.parseInt(value);
        } else {
            logger.error("流程模版[{}]中的节点[{}]中未知数据类型[{}],值为[{}]", flowTemplateName, nodeKey, type, value);
            return null;
        }
    }

    /**
     * 给对象属性赋值
     *
     * @param o            被赋值的对象
     * @param propertyName 属性名称
     * @param value        值
     * @return true 赋值成功,false失败
     */
    public static boolean setValueToObject(Object o, String propertyName, Object value) {

        Class<?> aClass = o.getClass();
        if (null != propertyName && !propertyName.startsWith(SETTER_START) && !propertyName.isEmpty()) {
            String firstLetter = propertyName.substring(0, 1).toUpperCase();
            propertyName = SETTER_START + firstLetter + propertyName.substring(1);
        }
        try {
            Method[] methods = aClass.getMethods();
            String simpleFormat = "yyyy-MM-dd HH:mm:ss";
            boolean flg = true;
            for (Method m : methods) {
                if (m.getName().equals(propertyName)) {
                    String simpleName = m.getParameterTypes()[0].getSimpleName().toLowerCase();
                    switch (simpleName) {
                        case "date":
                            try {
                                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(simpleFormat);
                                Date parse = simpleDateFormat.parse(value.toString());
                                m.invoke(o, parse);
                            } catch (RuntimeException ex) {
                                throw ex;
                            } catch (Exception ex) {
                                logger.error("日期类型的数据目前仅仅支持[{}]格式", simpleFormat);
                                flg = false;
                            }
                            break;
                        case "int":
                            int i = Integer.parseInt(value.toString());
                            m.invoke(o, i);
                            break;
                        case "short":
                            short s = Short.parseShort(value.toString());
                            m.invoke(o, s);
                            break;
                        case "byte":
                            byte b = Byte.parseByte(value.toString());
                            m.invoke(o, b);
                            break;
                        case "double":
                        case "float":
                            double v = Double.parseDouble(value.toString());
                            m.invoke(o, v);
                            break;
                        case "boolean":
                            Boolean aBoolean = Boolean.valueOf(value.toString());
                            m.invoke(o, aBoolean);
                            break;
                        case "char":
                            m.invoke(o, value.toString());
                            break;
                        default:
                            m.invoke(o, value);
                            break;
                    }
                    break;
                }
            }
            return flg;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            logger.error("ObjectTools:发生异常:{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 测试某个类是否实现了制定接口
     *
     * @param fromClass       类信息
     * @param targetInterface 接口信息
     * @return true:类实现了指定接口,false:可能是参数传入为null或者没有实现
     */
    public static boolean testClassImplementsInterface(Class<?> fromClass, Class<?> targetInterface) {
        if (fromClass == null || targetInterface == null) {
            return false;
        }
        return targetInterface.isAssignableFrom(fromClass);
    }
}
